package util3;

import org.junit.jupiter.api.Test;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author YanZhen_Li
 * @version 1.0
 * @title DateFormeatUtil
 * @description
 * @create 2023/11/23 13:15
 */
public class DateFormatUtil {
    /**
     * 支持解析的格式汇总
     */
    private static final String[] FORMAT = {
            "yyyy-MM-dd HH:mm:ss.sss",
            "yyyy-MM-dd HH:mm:ss",
            "yyyy/MM/dd HH:mm:ss",
            "yyyy-MM-dd'T'HH:mm:ss",
            "yyyy年MM月dd日 ahh:mm:ss",
            "yyyyMMddHHmmss",
            "yyyy-MM-dd",
            "yyyy/MM/dd",
            "yyyyMMdd",
    };

    /**
     * 转义格式汇总
     */
    private static final TreeMap<String, String> RULE_TREE_MAP = new TreeMap<>((s1, s2) -> s1.length() - s2.length() != 0?s2.length() - s1.length():s2.compareTo(s1));

    /**
     * 不要要求那么高，已经匹配了90%的场景了，如果没匹配到你的场景，说明你们的数据传入格式确实很不规范，请再添加这个集合
     */
    static {
        // 不能用\\d+，否则匹配yyyy-MM-dd的时候会重新匹配d，这个时候会发生问题
        RULE_TREE_MAP.put("y", "[0-9]+");
        RULE_TREE_MAP.put("M", "[0-9]+");
        RULE_TREE_MAP.put("d", "[0-9]+");
        RULE_TREE_MAP.put("H", "[0-9]+");
        RULE_TREE_MAP.put("h", "[0-9]+");
        RULE_TREE_MAP.put("m", "[0-9]+");
        RULE_TREE_MAP.put("s", "[0-9]+");
        RULE_TREE_MAP.put("S", "[0-9]+");
        RULE_TREE_MAP.put("a", "[上下]午");
        RULE_TREE_MAP.put(" ", "\\s");
        RULE_TREE_MAP.put("'", "");
    }

    /**
     * 需要转义的特殊字符
     */
    private static final Set<String> CHART_SET = new HashSet<>();

    /**
     * 这里如果设置的字符不够的话请后续补充
     */
    static {
        CHART_SET.add(".");
        CHART_SET.add("*");
        CHART_SET.add(",");
        CHART_SET.add("{");
        CHART_SET.add("}");
        CHART_SET.add("[");
        CHART_SET.add("]");
        CHART_SET.add("(");
        CHART_SET.add(")");
        CHART_SET.add("/");
        CHART_SET.add("-");
        CHART_SET.add("|");
        CHART_SET.add("+");
        CHART_SET.add("?");
        CHART_SET.add("!");
        CHART_SET.add("^");
        CHART_SET.add("$");
    }

    /**
     * 格式化所有的格式为正则表达式
     */
    private static final TreeMap<String, Pattern> FORMAT_REGULAR = new TreeMap<>((s1, s2) -> s1.length() - s2.length() != 0?s2.length() - s1.length():s2.compareTo(s1));

    static {
        for (String formatStr : FORMAT) {
            // 过滤特殊字符
            String regular = formatStr.replace("\\", "\\\\");
            for (String s : CHART_SET) {
                regular = regular.replace(s, "\\" + s);
            }
            // 设置所有匹配项
            Set<String> keySet = RULE_TREE_MAP.keySet();
            for (String s : keySet) {
                String ruleStr = RULE_TREE_MAP.get(s);
                regular = regular.replace(s, ruleStr);
            }
            regular = "^" + regular + "$";
            FORMAT_REGULAR.put(formatStr, Pattern.compile(regular));
        }
    }

    /**
     * 这个方法会根据我们传入的字符串自动识别，让后转换成我们系统能识别的Date
     *
     * @param dateStr 传入的日期字符串
     * @return 格式化之后的日期
     * @throws ParseException
     */
    public static Date format(String dateStr) throws ParseException {
        Set<String> keySet = FORMAT_REGULAR.keySet();
        String formeat = null;
        for (String key : keySet) {
            Pattern value = FORMAT_REGULAR.get(key);
            Matcher matcher = value.matcher(dateStr);
            if (matcher.lookingAt()) {
                formeat = key;
                break;
            }
        }
        if (formeat == null) {
            throw new RuntimeException("没有匹配的日期时间类型！！！");
        } else {
            DateFormat dateFormat = new SimpleDateFormat(formeat);
            return dateFormat.parse(dateStr);
        }
    }

    @Test
    public void test001() throws ParseException {
        System.out.println(format("2023-11-12 11:12:13"));
        System.out.println(format("2023-11-12 11:12:13.333"));
        System.out.println(format("2023/11/12 11:12:13"));
        System.out.println(format("2023-11-12T11:12:13"));
        System.out.println(format("2023年11月12日 下午11:12:13"));
        System.out.println(format("20231112111213"));
        System.out.println(format("2023-11-12"));
        System.out.println(format("2023/11/12"));
        System.out.println(format("20231112"));
    }
}
